package cn.lei.netty.herostory;

import cn.lei.netty.herostory.cmdhandler.CmdHandlerFactory;
import cn.lei.netty.herostory.mq.MqProducer;
import cn.lei.netty.herostory.util.RedisUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 服务器入口类
 *
 * @author lil
 */
public class ServerMain {
    /**
     * 日志对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ServerMain.class);

    /**
     * 服务器端口号
     */
    private static final int SERVER_PORT = 12345;

    /**
     * 应用主函数
     *
     * @param args 命令行参数数组
     */
    public static void main(String[] args) {
        //设置log4j属性文件
        PropertyConfigurator.configure(ServerMain.class.getClassLoader().getResourceAsStream("log4j.properties"));

        //初始化命令处理器工厂
        CmdHandlerFactory.init();

        //初始化消息识别器
        GameMsgRecognizer.init();

        //初始化mysql会话工厂
        MySqlSessionFactory.init();

        //初始化 Redis
        RedisUtil.init();

        //初始化消息队列
        MqProducer.init();

        //拉客的
        EventLoopGroup bossGroup = new NioEventLoopGroup();

        //干活的
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        //服务启动辅助类
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup);
        //服务信道方式
        b.channel(NioServerSocketChannel.class);
        b.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                //channel初始化后回调,可添加自定义处理
                ch.pipeline().addLast(
                        new HttpServerCodec(),//HTTP 服务器解码器
                        new HttpObjectAggregator(65535), //内容限制
                        new WebSocketServerProtocolHandler("/websocket"),// webSocket协议处理器,在这里处理协议握手,ping,pong等消息
                        new GameMsgDecoder(),//自定义消息解码器
                        new GameMsgEncoder(),//自定义消息编码器
                        new GameMsgHandler() //自定义消息处理器

                );
            }
        });

        try {
            //绑定12345端口号(注意:实际项目中会使用args中的参数来指定)
            ChannelFuture f = b.bind(SERVER_PORT).sync();

            if (f.isSuccess()) {
                LOGGER.info("服务器启动成功!");
            }

            //等待服务器信道关闭(不立即退出程序,让应用程序一直提供服务)
            f.channel().closeFuture().sync();

        } catch (Exception ex) {
            //服务器遇到异常,打印详细的错误信息
            LOGGER.error(ex.getMessage(), ex);
        } finally {
            //关闭服务器
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}
